﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Face_Recognition
{
    public class IntegralImage
    {
        int[,] integral;
        int[,] squaredIntergral;
        Bitmap bitmap;

        public Bitmap Bitmap
        {
            get { return bitmap; }
            set { bitmap = value; }
        }

        public int[,] SquaredIntergral
        {
            get { return squaredIntergral; }
            set { squaredIntergral = value; }
        }

        public int[,] Integral
        {
            get { return integral; }
            set { integral = value; }
        }
        short[,] grayscaleImage;
        int width, height;

        public int Height
        {
            get { return height; }
            set { height = value; }
        }

        public int Width
        {
            get { return width; }
            set { width = value; }
        }

        public IntegralImage(Bitmap bitmap)
        {
            width = bitmap.Width+1;
            height = bitmap.Height+1;

            this.bitmap = bitmap;

            grayscaleImage = new short[height, width];
            integral = new int[height, width];
            squaredIntergral = new int[height, width];

           // computeGrayscaleImage(bitmap);
            this.computeGrayscaleImageFlat(bitmap, Color.Red);
            computeIntegralImage();
        }

        private void computeIntegralImage()
        {
            for (int w = 1; w < width; w++)
            {
                for (int h = 1; h < height; h++)
                {
                    integral[h,w] += grayscaleImage[h, w];
                    squaredIntergral[h, w] += grayscaleImage[h, w] * grayscaleImage[h, w];

                        integral[h, w] += integral[h, w - 1];
                        integral[h, w] += integral[h - 1, w];
                        integral[h, w] -= integral[h - 1, w - 1];

                        squaredIntergral[h, w] += squaredIntergral[h, w - 1];
                        squaredIntergral[h, w] += squaredIntergral[h - 1, w];
                        squaredIntergral[h, w] -= squaredIntergral[h - 1, w - 1];             
                }
            }
        }

        private void computeGrayscaleImage(Bitmap bitmap)
        {
            for (int w = 1; w < width; w++)
            {
                for (int h = 1; h < height; h++)
                {
                    grayscaleImage[h, w] = (short)(0.21 * bitmap.GetPixel(w-1, h-1).R + 0.71 * bitmap.GetPixel(w-1, h-1).G + 0.07 * bitmap.GetPixel(w-1, h-1).B);
                }
            }
        }

        private void computeGrayscaleImageFlat(Bitmap bitmap, Color color)
        {
            short min = 255;
            short max = 0;

            for (int w = 1; w <width; w++)
            {
                for (int h = 1; h <height; h++)
                {
                    if (color == Color.Red)
                        grayscaleImage[h, w] = (short)(bitmap.GetPixel(w-1, h-1).R);
                    if (color == Color.Green)
                        grayscaleImage[h, w] = (short)(bitmap.GetPixel(w-1, h-1).G);
                    if (color == Color.Blue)
                        grayscaleImage[h, w] = (short)(bitmap.GetPixel(w-1, h-1).B);

                    if (grayscaleImage[h, w] > max)
                        max = grayscaleImage[h, w];

                    if (grayscaleImage[h, w] < min)
                        min = grayscaleImage[h, w];
                }
            }
            grayscaleImage = Normalization.LinearStretch(grayscaleImage,min,max);
        }

        public int GetRectangleSum(int x, int y, int _width, int _height)
        {
            return integral[y, x] + integral[y, x + _width] - integral[y +_height,x] - integral[y + _height,x + _width];
        }

        public int GetSum(int x, int y, int width, int height)
        {
                return Integral[y + height, x + width] + Integral[y, x] - Integral[y, x + width] - Integral[y + height,x];        
        }
        public int GetSquaredSum(int x, int y, int width, int height)
        { 
                return SquaredIntergral[y + height, x + width] + SquaredIntergral[y, x] - SquaredIntergral[y, x + width] - SquaredIntergral[y + height, x];
        }
    }
}
